feat(schematics): rewrite Vertex AI imports to AI Logic on ng update - #3725
feat(schematics): rewrite Vertex AI imports to AI Logic on ng update#3725armando-navarro wants to merge 1 commit into
Conversation
AngularFire 21 renamed the Vertex AI module to Firebase AI Logic: the @angular/fire/vertexai and older @angular/fire/vertexai-preview entry points were removed in favor of @angular/fire/ai, and the exported symbols were renamed (getVertexAI to getAI, provideVertexAI to provideAI, VertexAI to AI, and so on). A workspace on 20 that used Vertex AI would fail to compile after the upgrade. Extend the existing v21 migration (which aligns the firebase dependency) to also rewrite these imports and their usages. The rewrite parses each source file with the TypeScript compiler and edits only genuine references, so it leaves strings, comments, and unrelated identifiers that merely share a name untouched. It handles named imports and their aliases, namespace imports in both value and type position, bare local re-exports, and shorthand properties. The one accepted limitation is name shadowing: because the rewrite matches by name, a local variable that shadows an imported name with the same spelling can be mis-renamed. ng update always presents its changes as a diff for review, so this is caught on inspection. Also add typescript to the schematics esbuild externals so the compiler is resolved from the workspace at ng-update time rather than bundled into the package, matching how Angular's own migrations ship. Docs: add a 20-to-21 upgrade guide, note the rename in the AI Logic guide, and link the upgrade guide from the README. Refs angular#3686
tyler-reitz
left a comment
There was a problem hiding this comment.
Nice work on the AST approach — the two-pass design holds up well under poking. The namespace and identifier passes can't double-edit the same token (isMemberOrDeclaredName catches the child visit in both value and type position), applyEdits sorting back-to-front is right, and the spec coverage is genuinely thorough: shorthand expansion, accessor look-alikes, destructuring keys vs. binding initializers, idempotency. *.jasmine.ts is picked up by tools/jasmine.ts, so these run in CI. The symbol map matches the real src/ai/public_api.ts exports for every entry except one — which is the blocker below.
1. getVertexAI → getAI is not a rename, and the rewrite silently changes which backend the app calls
getVertexAI and getAI both existed in the old module. git show ac3dd7c^:src/vertexai/firebase.ts exports all four of getAI, getVertexAI, getGenerativeModel, getImagenModel. Two coexisting functions aren't a rename pair.
getAI() with no options defaults to the Google AI (Gemini Developer API) backend; the Vertex equivalent is getAI(app, { backend: new VertexAIBackend() }). So a user on Vertex who runs ng update ends up with code that compiles and then talks to a different API, with different enablement and billing. Nothing in the diff would look wrong on review, which defeats the "ng update always shows its changes as a diff" safety net cited under Known limitation.
Two ways out:
- rewrite
getVertexAI(...)togetAI(app, { backend: new VertexAIBackend() }), addingVertexAIBackendto the rewritten import, or - leave
getVertexAIcalls alone andcontext.logger.warnwith a pointer to the upgrade guide.
Worth confirming the SDK's default backend against @firebase/ai before picking. The symbol table in docs/version-21-upgrade.md and the note added to docs/ai.md need the same correction — as written, both teach the rename as safe.
2. export { VertexAI } from '@angular/fire/vertexai' renames the user's public export
src/schematics/update/v21/vertexai-to-ai.ts:181 — collectSpecifierEdit rewrites importedNameNode, which is element.name when there's no propertyName. For a re-export with a from clause that produces export { AI } from '@angular/fire/ai', so the file's external export name changes from VertexAI to AI and downstream consumers break.
identifierUsageEdit already handles this correctly for the bare local re-export — expanding to export { AI as VertexAI }, with a good comment explaining why. The from-clause path should do the same. (export { VertexAI as Foo } from '...' is already correct, since propertyName is set.)
3. The migration walks node_modules when a project has no sourceRoot
rewriteVertexAIToAI derives roots from sourceRoot || root. A root project with root: "" and no sourceRoot — which older CLI versions generate — gives posix.join('/', '') → /, and every path in the tree passes the prefix test. The content.includes(specifier) prefilter keeps most files from being parsed, but any dependency that re-exports @angular/fire/vertexai gets rewritten in place inside node_modules.
A filePath.includes('/node_modules/') guard is the usual fix and costs nothing.
4. Step ordering interacts badly with the typescript external
Making typescript an esbuild external is the right call for package size, but it isn't declared anywhere in src/package.json — unlike firebase-tools, which is an optional peer. Under a strict or isolated node_modules layout the top-level import * as ts fails at module load, which takes down the whole migration.
Because src/schematics/update/v21/index.ts:14 runs the rewrite before alignFirebaseVersion, that failure also costs users the firebase-12 alignment — the part they genuinely can't do without. Two small changes: declare typescript as an optional peer dependency, and run alignFirebaseVersion first so a rewrite failure can only cost you the rewrite.
5. Not covered: direct firebase/vertexai imports
Since this migration also moves users to Firebase JS SDK 12, where that entry point is gone, direct SDK imports break too. The guide flags it as manual, but the same AST pass would handle it with one more entry in OLD_MODULE_SPECIFIERS — worth considering, subject to the same getVertexAI caveat above.
Merge order
This is stacked on unmerged predecessor work, and it edits the same README feature-table region as #3724 (that PR re-flows the row boundaries around the last two cells; this one rewrites the Vertex AI cell's content). Whichever lands second will need a manual rebase.
tyler-reitz
left a comment
There was a problem hiding this comment.
Marking this as changes-requested to hold the merge, per my earlier review.
The blocker is item 1: getVertexAI and getAI coexisted in the old module (git show ac3dd7c^:src/vertexai/firebase.ts exports both), so rewriting one to the other isn't a rename — it moves a Vertex user onto the Google AI backend silently, and the resulting diff looks correct on inspection. That needs resolving in the migration and in both docs pages before this lands.
Items 2-4 (the export { X } from public-export rename, the node_modules walk when sourceRoot is absent, and the typescript external / step-ordering interaction) are smaller but concrete. Item 5 is optional.
Happy to re-review once the backend question is settled.
Adds an
ng updatemigration that moves a workspace off the Vertex AI module onto Firebase AI Logic, and a guide for upgrading from AngularFire 20 to 21.Background
AngularFire 21 renamed the Vertex AI module to Firebase AI Logic. The
@angular/fire/vertexaientry point (and the older@angular/fire/vertexai-preview) were removed in favor of@angular/fire/ai, and the exported symbols were renamed. A project upgrading from 20 that used Vertex AI would fail to compile until it updated those imports by hand.What this does
firebasedependency) to also rewrite Vertex AI imports and their usages to AI Logic. It parses each source file with the TypeScript compiler and edits only real references, leaving strings, comments, and unrelated identifiers that happen to share a name untouched. It handles named imports and aliases, namespace imports in value and type position, bare local re-exports, and shorthand properties.docs/version-21-upgrade.md, a note indocs/ai.md, and a README link.typescriptto the schematics esbuild externals, so the compiler is resolved from the workspace atng updatetime rather than bundled into the package. This matches how Angular's own migrations ship and keeps the package from growing by several megabytes.Symbol map
@angular/fire/vertexai)@angular/fire/ai)getVertexAIgetAIprovideVertexAIprovideAIVertexAIAIVertexAIInstancesAIInstancesvertexAIInstance$AIInstance$VertexAIModuleAIModulegetGenerativeModelandgetImagenModelkeep their names.Known limitation
The rewrite matches by name, so a local variable that shadows an imported name with the same spelling can be mis-renamed.
ng updatealways shows its changes as a diff to review, so this surfaces on inspection.Verification
Unit specs cover each kind of code the migration can run into:
ns.getVertexAI()) and type position (ns.VertexAI){ getVertexAI }) and bare local re-exports (export { VertexAI })I also ran the migration for real, not just in specs:
@angular/fire/vertexaing updateand confirmed every import and usage rewrote to@angular/fire/aifirebasealigned to^12.4.0, and that a second run made no changesRefs #3686